import React, { useEffect, useRef, useState } from 'react'
// import * as dat from 'dat.gui';

interface IParticle {
  radians: number;
  x: number;
  y: number;
  speed: number;
  radius: number;
  size: number;
  hue: number;
  brightness: number;
  alpha: number;
}
/**
 * [连续发射demo](http://www.wuweierwei.com/old/html5/firework.html)
 * [基于dat.gui for codepen](https://codepen.io/jackrugile/pen/acAgx)
 * [掘金博客 - 书签调用脚本](https://juejin.cn/post/6916930617166807054)
 */
export default function firework() {
  // 因为 current 为只读属性，若需要直接修改useRef的结果，则在泛型参数的类型中包含 | null
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
  const rafRef = useRef<number>(NaN);
  // state的问题在于一旦修改了它就会造成组件的重新渲染: 细分state
  const [context, setContext] = useState<CanvasRenderingContext2D | null>(null);

  /**
   * resize handler
   */
  const resizeCanvas = () => {
    if (!canvasRef || !canvasRef.current) return;
    canvasRef.current.width = window.innerWidth;
    canvasRef.current.height = window.innerHeight;
  }

  /**
   * 清空画布
   */
  const clearCanvas = () => {
    if (!canvasRef || !canvasRef.current || !context) return;
    context.fillStyle = '#000000';
    context.fillRect(0, 0, canvasRef.current.width, canvasRef.current.height);
  }

  /**
   * mouseDown(鼠标左右键) handler
   */
  const mouseDownHandler = (e: MouseEvent) => {
    var x = e.clientX;
    var y = e.clientY;
    fire(x, y);
  }

  /**
   * fireworks 动画
   * @param x 
   * @param y 
   */
  function fire(x: number, y: number) {
    const aParticles = createFireworks(x, y);
    function tick() {
      if (!canvasRef || !canvasRef.current || !context) return;
      // tips: 烟雾拖尾
      context.globalCompositeOperation = 'destination-out';
      context.fillStyle = 'rgba(0,0,0,' + 10 / 100 + ')';
      context.fillRect(0, 0, canvasRef.current.width, canvasRef.current.height);
      context.globalCompositeOperation = 'lighter';
      drawFireworks(aParticles);
      rafRef.current = requestAnimationFrame(tick);
    }
    cancelAnimationFrame(rafRef.current);
    tick();
  }

  /**
   * 创建 fireworks 数组
   * @param sx 
   * @param sy 
   */
  const createFireworks = (sx: number, sy: number): Array<IParticle> => {
    var particles = [];
    var hue = Math.floor(Math.random() * 51) + 150;
    var hueVariance = 30;
    var count = 100;
    for (var i = 0; i < count; i++) {
      var p: IParticle = {
        radians: NaN,
        x: NaN,
        y: NaN,
        speed: NaN,
        radius: NaN,
        size: NaN,
        hue: NaN,
        brightness: NaN,
        alpha: NaN,
      };
      var angle = Math.floor(Math.random() * 360);
      p.radians = angle * Math.PI / 180;
      p.x = sx;
      p.y = sy;
      p.speed = (Math.random() * 5) + .4;
      p.radius = p.speed;
      p.size = Math.floor(Math.random() * 3) + 1;
      p.hue = Math.floor(Math.random() * ((hue + hueVariance) - (hue - hueVariance))) + (hue - hueVariance);
      p.brightness = Math.floor(Math.random() * 31) + 50;
      p.alpha = (Math.floor(Math.random() * 61) + 40) / 100;
      particles.push(p);
    }
    return particles;
  }

  /**
   * 根据当前数组画出每一帧的图像
   * @param particles 
   */
  function drawFireworks(particles: Array<IParticle>) {
    clearCanvas();
    for (var i = 0; i < particles.length; i++) {
      var p = particles[i];
      // tips: 重力的影响
      var vx = Math.cos(p.radians) * p.radius;
      var vy = Math.sin(p.radians) * p.radius + 0.4;
      p.x += vx;
      p.y += vy;
      p.radius *= 1 - p.speed / 100;
      p.alpha -= 0.005;

      if (!context) return;
      context.beginPath();
      context.arc(p.x, p.y, p.size, 0, Math.PI * 2, false);
      context.closePath();
      context.fillStyle = 'hsla(' + p.hue + ', 100%, ' + p.brightness + '%, ' + p.alpha + ')';
      context.fill();
    }
  }

  useEffect(() => {
    if (!canvasRef || !canvasRef.current) return;
    setContext(canvasRef.current.getContext('2d'));
    if (!context) return;
    // var ua = navigator.userAgent.toLowerCase();
    // // bgImg=(ua.indexOf('iphone')!=-1||ua.indexOf('ipad')!=-1||ua.indexOf('ipod')!=-1)?"images/firework_1_bg.jpg":"images/firework_bg.jpg";
    // console.log(ua);
    window.addEventListener('resize', resizeCanvas, false);
    resizeCanvas();
    clearCanvas();
    document.addEventListener('mousedown', mouseDownHandler, false);
  });
  return (
    <>
      <div className="firework-container w-screen h-screen">
        <div className="mountains2"></div>
        <div className="mountains1"></div>
        <div className="skyline"></div>
        <style jsx>
          {`
          .firework-container {
            right: 0;
            position: fixed;
            top: 0;
            z-index: 3;
            background: #171717;
          }
          .skyline {
            background: url(https://jackrugile.com/lab/fireworks-v2/images/skyline.png) repeat-x 50% 0;
            bottom: 0;
            height: 135px;
            left: 0;
            position: absolute;
            width: 100%;
            z-index: 1;	
          }
          
          .mountains1 {
            background: url(https://jackrugile.com/lab/fireworks-v2/images/mountains1.png) repeat-x 40% 0;
            bottom: 0;
            height: 200px;
            left: 0;
            position: absolute;
            width: 100%;
            z-index: 1;	
          }
          
          .mountains2 {
            background: url(https://jackrugile.com/lab/fireworks-v2/images/mountains2.png) repeat-x 30% 0;
            bottom: 0;
            height: 250px;
            left: 0;
            position: absolute;
            width: 100%;
            z-index: 1;	
          }
          canvas {
            cursor: crosshair;
            display: block;
            position: relative;
            z-index: -1;
          }
        `}
        </style>
        <canvas ref={canvasRef} />
      </div>
      <div id="gui"></div>
    </>
  )
}
